#!/bin/bash
#{  fstags - manage tags for your files
#   Copyright (C) 2007  Victor Bogado and Rodolfo Borges
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public License
#   as published by the Free Software Foundation; either version 2
#   of the License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#}

test -n "$tag_dir" || tag_dir="$HOME/.tags"
function usage()
{
	echo "usage:"
	echo "tag [FILES]"
	echo "Lists tags that are associated to the files."
	echo
	echo "tag [FILES] -s [TAGS]"
	echo "Sets the tags passed to all the files specified."
	echo
	echo "tag -f [TAGS]"
	echo "find the files that have all the tags specified."
	echo 
	echo "ex.:"
	echo "Sets the tags \"configuration\" and \"network\" to the file \"/etc/hosts\" and then sets \"configuration\" and \"groups\" to the file \"/etc/group\""
	echo "$ tag /etc/hosts -s configuration network"
	echo "$ tag /etc/hosts -s configuration group"
	echo 
	echo "list the tags associated with the file \"/etc/group\" and \"/etc/hosts\""
	echo "$ tag /etc/group /etc/hosts"
	echo 
	echo "Lists the files tagged as \"configuration\""
	echo "$ tag -f configuration"
	echo 
	echo "List the files tagged as \"configuration\" and \"network\", in this sample this must show only the file \"/etc/hosts\""
	echo "$ tag -f configuration network"
}

declare -a files

function file_id()
{
	stat -c "%i" "$1"
}

function add_file()
{
	if test -e "$1"; then
		files[${#files[*]}]="$1"
	else
		stat "$1"
	fi
}

function create_tag()
{
	# create the dir for this tag, if it does not exist yet
	test -d "$tag_dir/$1" || mkdir -p "$tag_dir/$1" || exit

	for i in "${files[@]}"; do

		# get full path
		case "$i" in
			/*)
				;;
			./*)
				i="$(echo "$PWD/$i" | sed 's/\/\.\//\//g')"
				;;
			*)
				i="$PWD/$i"
				;;
		esac

		# create new tag, if it does not exist yet
		local target="$tag_dir/$1/`file_id "$i"`"
		if test -e "$target"; then
			echo "tag $1 for file $i already exists" >/dev/stderr
		else
			ln -s "$i" "$target"
		fi

	done
}

function show_tags()
{
	for i in "${files[@]}"; do
		if test -e "$i"; then
			local msg="$i:"
			if test -d "$tag_dir"; then
				for j in $( find "$tag_dir/" -name "`file_id "$i"`" -printf "%P\n" | sort ); do  #FIXME: handle \s in $tag_dir
					msg="$msg $(dirname "$j")"
				done
			fi
			echo "$msg"
		else
			echo "$i: no such file or directory" >/dev/stderr
		fi
	done
}

function find_tags()
{
	local tag0="$1"
	shift
	for i in "$tag_dir/$tag0"/*; do
		test -L "$i" || continue
		local ok=1
		for j in "$@"; do
			if ! test -L "$tag_dir/$j/`basename $i`"; then
				ok=0
				break
			fi
		done
		test $ok == 1 && readlink "$i"
	done
}

function main()
{
	while test -n "$1"; do
		case "$1" in
			-s)
				shift
				while test -n "$1"; do
					create_tag "$1"
					shift
				done
				exit
				;;
			-f)
				shift
				find_tags "$@" | sort
				exit
				;;
			*)
				add_file "$1"
				;;
		esac
		shift
	done

	if test -n "${files[0]}"; then
		show_tags
	else
		usage
	fi
}

main "$@"

# bash bug?
#function show_tags()
#{
#	for i in "${files[@]}"; do
#		echo -n "$i:"
#		if test -d "$tag_dir"; then
#			for j in $( find "$tag_dir/" -name "$( stat -c "%i" "$i" )" -printf "%P\n" ); do
#				#echo "j($j)"
#				echo -n " $(dirname "$j")"
#			done
#			echo
#		fi
#	done
#}

# vim600:fdm=marker:fmr={,}:
